package user.losacorp.xml;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.logging.Level;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

public class FeedParser extends DefaultHandler {

	private static String NOMBRE_ARCHIVO = "feed.xml";

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// We use a SAXParserFactory to obtain a SAXParser, which
		// encapsulates a SAXReader.
		SAXParserFactory factory = SAXParserFactory.newInstance();
		factory.setValidating(false);
		// Create a SAXParser object from the factory
		try {
			SAXParser parser = factory.newSAXParser();
			// Now parse the file specified on the command line using
			// an instance of this class to handle the parser callbacks
			parser.parse(new File(NOMBRE_ARCHIVO), new FeedParser());
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	private StringBuffer accumulator;
	private String entryID;
	private String entryTitle;
	private String entryHref;
	private String entryPublished;
	private String entryUpdated;
	private String entryContentType;
	private String entryContent;
	private LinkedList<EntryFeed> entryList;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.xml.sax.helpers.DefaultHandler#startDocument()
	 */
	@Override
	public void startDocument() throws SAXException {
		accumulator = new StringBuffer();
		entryList = new LinkedList<EntryFeed>();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
	 */
	@Override
	public void characters(char[] buffer, int start, int length)
			throws SAXException {
		accumulator.append(buffer, start, length);
	}

	/*
	 * At the beginning of each new element, erase any accumulated text.
	 * 
	 * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
	 * java.lang.String, java.lang.String, org.xml.sax.Attributes)
	 */
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		accumulator.setLength(0);
		if (qName.equals("link")) {
			entryHref = attributes.getValue("href");
		} else if (qName.equals("content")) {
			entryContentType = attributes.getValue("type");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
	 * java.lang.String, java.lang.String)
	 */
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if (qName.equals("id")) {
			entryID = accumulator.toString().trim();
		} else if (qName.equals("title")) {
			entryTitle = accumulator.toString().trim();
		} else if (qName.equals("published")) {
			entryPublished = accumulator.toString().trim();
		} else if (qName.equals("updated")) {
			entryUpdated = accumulator.toString().trim();
		} else if (qName.equals("content")) {
			entryContent = accumulator.toString().trim();
		} else if (qName.equals("entry")) {
			EntryFeed entry = new EntryFeed(entryID, entryTitle, entryHref,
					entryPublished, entryUpdated, entryContentType,
					entryContent);
			entryList.add(entry);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.xml.sax.helpers.DefaultHandler#endDocument()
	 */
	@Override
	public void endDocument() throws SAXException {
		System.out.println("Mostrando contenido del archivo.");
		for (Iterator<EntryFeed> iterator = entryList.iterator(); iterator
				.hasNext();) {
			EntryFeed entry = iterator.next();
			System.out.println("Entrada: \t" + entry.getEntryID());
			System.out.println("Titulo: \t" + entry.getEntryTitle()
					+ "\nLink: \t" + entry.getEntryHref() + "\n\tPublicada: "
					+ entry.getEntryPublished() + "\nActualizada: \t"
					+ entry.getEntryUpdated() + "\nContenido de tipo "
					+ entry.getEntryContentType() + ": \n\t"
					+ entry.entryContent);
		}
	}

	/*
	 * Issue a warning
	 * 
	 * @see
	 * org.xml.sax.helpers.DefaultHandler#warning(org.xml.sax.SAXParseException)
	 */
	@Override
	public void warning(SAXParseException exception) throws SAXException {
//		System.err.println("WARNING: line " + exception.getLineNumber() + ": "
//				+ exception.getMessage());
		FeedFactory.logger.log(Level.SEVERE, "WARNING: line " + exception.getLineNumber() + ": ", exception.getMessage());

	}

	/*
	 * Report a parsing error
	 * 
	 * @see
	 * org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException)
	 */
	@Override
	public void error(SAXParseException exception) throws SAXException {
//		System.err.println("ERROR: line " + exception.getLineNumber() + ": "
//				+ exception.getMessage());
		FeedFactory.logger.log(Level.SEVERE, "ERROR: line " + exception.getLineNumber() + ": ", exception.getMessage());

	}

	/*
	 * Report a non-recoverable error and exit
	 * 
	 * @see
	 * org.xml.sax.helpers.DefaultHandler#fatalError(org.xml.sax.SAXParseException
	 * )
	 */
	@Override
	public void fatalError(SAXParseException exception) throws SAXException {
//		System.err.println("FATAL: line " + exception.getLineNumber() + ": "
//				+ exception.getMessage());
		FeedFactory.logger.log(Level.SEVERE, "FATAL: line " + exception.getLineNumber() + ": ", exception.getMessage());
		throw (exception);
	}

	public class EntryFeed {

		private String entryID;
		private String entryTitle;
		private String entryHref;
		private String entryPublished;
		private String entryUpdated;
		private String entryContentType;
		private String entryContent;

		public EntryFeed(String entryID, String entryTitle, String entryHref,
				String entryPublished, String entryUpdated,
				String entryContentType, String entryContent) {
			this.entryID = entryID;
			this.entryTitle = entryTitle;
			this.entryHref = entryHref;
			this.entryPublished = entryPublished;
			this.entryUpdated = entryUpdated;
			this.entryContentType = entryContentType;
			this.entryContent = entryContent;
		}

		/**
		 * @return the entryID
		 */
		public String getEntryID() {
			return entryID;
		}

		/**
		 * @return the entryTitle
		 */
		public String getEntryTitle() {
			return entryTitle;
		}

		/**
		 * @return the entryHref
		 */
		public String getEntryHref() {
			return entryHref;
		}

		/**
		 * @return the entryPublished
		 */
		public String getEntryPublished() {
			return entryPublished;
		}

		/**
		 * @return the entryUpdated
		 */
		public String getEntryUpdated() {
			return entryUpdated;
		}

		/**
		 * @return the entryContentType
		 */
		public String getEntryContentType() {
			return entryContentType;
		}

		/**
		 * @return the entryContent
		 */
		public String getEntryContent() {
			return entryContent;
		}

	}

}
